<?php
/**
 * Geneone: Content Management Framework
 * Object Class
 *
 * http://geneone.neondragon.net/
 *
 * @package Geneone
 * @author Khlo
 * @version 1.0
 * @copyright 2004-2006 Geneone Development Team
 */
 
define ('GENE_OBJECT_UNCACHED', 1);
 
class Gene_Object {
	/**
	 * Get an object and return.
	 *
	 * @static
	 * @var int/string $id Object ID or Alias
	 * @var bool $aliases Whether aliases can be used
	 * @return object Instance of object
	 */
	function &get($id, $aliases=false) {
		$db =& Gene::getDatabase();
		
		require_once ("Gene/Object/Model.php");
		
		$o =& Gene_Object::getCachedObject($id);
		
		if ($o == GENE_OBJECT_UNCACHED) {
			// Integers are IDs, Aliases are anything else. Simple.
			if (!$aliases OR is_numeric($id)) {
				$q = $db->prepare("SELECT o.*, u.name FROM ".Gene::tableName("objects")." o LEFT JOIN ".Gene::tableName("user_info")." u ON (o.owner_id=u.user_id) WHERE object_id=?");
			} else {
				$id = strtolower($id);
				$q = $db->prepare("SELECT o.*, u.name FROM ".Gene::tableName("objects")." o LEFT JOIN ".Gene::tableName("user_info")." u ON (o.owner_id=u.user_id) WHERE alias=?");
			}
			$res = $q->execute(array($id));
			
			if ($row = $res->fetchRow()) {
				$res->free();
				Gene_Object::cacheObject($id, $row);
				$o =& Gene_Object::getCachedObject($id);
			} else {
				$o = false;
			}
		}
		
		return $o;
	}
	
	/**
	 * Create a new object.
	 *
	 * @static
	 *
	 * @var string $type Object Type
	 * @var string $title Object Title
	 * @var string $desc Object Description
	 * @var string $content Object Contents
	 * @var object $parentobj Instance of parent object
	 * @var array $options New Object options
	 *
	 * @return mixed Returns the object ID of the newly created object
	 *               on success or a PEAR_Error object containing a
	 *               descriptive error message on failure.
	 */
	function create($type, $title='', $desc='', $content='', &$parentobj, $options=array()) {
		require_once ("Gene/Object/Model.php");
		
		return Gene_Object_Model::create($type, $title, $desc, $content, $parentobj, $options);
	}
	
	/**
	 * Checks whether the user can perform a certain action.
	 *
	 * @var array $object Object Info Array
	 * @var string $name Permission Name
	 *
	 * @return boolean
	 */
	function checkPermission(&$object, $name) {
		$user =& Gene::getUser();
		if (!in_array($name, array("view", "edit", "revisions", "write", "moderate"))) {
			return false;
		}
		
		$usermasks = $user->getPermissionMasks();
		$objectmasks = explode(",", $object['p_'.$name]);
		
		$userid = $user->getUserId();

		foreach ($objectmasks as $i) {
			if ($i == "o") {
				if ($object['owner_id'] == $userid && $userid > 0) {
					return true;
				}
			} else if (in_array($i, $usermasks)) {
				return true;
			}
		}
		
		if ($name != "moderate") {
			return Gene_Object::checkPermission($object, "moderate");
		}
	}
	
	/**
	 * Process input HTML.
	 *
	 * Removes harmful HTML code if required.
	 *
	 * @static
	 * @var $content string HTML Code
	 * @return string Processed HTML Code
	 */
	function cleanHtml($content) {
		/* Safe HTML */
		$user =& Gene::getUser();
		
		if (!$user->hasPermission("namespaces.object.markup.fullhtml")) {
			require_once ("HTML/Safe.php");
			$parser =& new HTML_Safe();
			
			// Disable forms and some other annoyances
			
			$parser->deleteTags = array(
				'applet', 'base',   'basefont', 'bgsound', 'blink',  'body',
				'embed',  'frame',  'frameset', 'head',    'html',   'ilayer',
				'iframe', 'layer',  'link',     'meta',    'object', 'style',
				'title',  'script', 'marquee',	'div', 'h1', 'h2', 'form',
				'input', 'textarea', 'button', 'select', 'fieldset', 'param',
				);
				
			$parser->cssKeywords = array(
				'absolute', 'behavior',       'behaviour',   'content', 'expression',
				'fixed',    'include-source', 'moz-binding', 'width', 'font', 'height',
				'background', 'url', 'padding', 'margin', 'border',
				);
				
			$content = $parser->parse($content);
		}
		
		return $content;
	}
	
	/**
	 * Generates an alias for provided text
	 *
	 * @static
	 * @var $text string Original Text
	 * @var $chars int Maximum Slug Length
	 * @return string Alias
	 */
	function generateAlias($text, $chars=40) {
		$slug = preg_replace('/\s\s+/', ' ', preg_replace("/[^a-zA-Z0-9 ]/", "", $text));
		if (strlen($slug) > $chars) {
			$slug = substr($slug, 0, $chars);
			$s = explode(" ", $slug);
			$c = count($s) - 1;
			unset($s[$c]);
			$slug = implode(" ", $s);
		}

		return str_replace(" ", "-", ucwords(strtolower($slug)));
	}
	
	/**
	 * Object Cache Function.
	 *
	 * @var int/string $id Object ID or Alias
	 * @var object/array $object Object to cache
	 */
	function &cacheObject($id, &$object) {
		static $objects = array();
		
		if ($object !== null) {
			/* Cache it */
			if ($object === false) {
				$objects[$id] = false;
			} else {
				if (!isset($objects[$id])) {
					if (is_array($object)) {
						$info = $object;
					} else {
						$info = $object->get();
					}
					
					if ($info['object_id'] != $id) {
						$id = $info['object_id'];
					}
					
					$objects[$id] = $object;
					
					$info['alias'] = strtolower($info['alias']);

					if (isset($info['alias']) && $info['alias'] && $info['alias'] != $id) {
						$objects[$info['alias']] = $info['object_id'];
					}
				}
			}
			
			$r = true;
		} else {
			/* Read cache */
			if (!is_numeric($id) && isset($objects[$id]) && isset($objects[$objects[$id]])) {
				$id = $objects[$id];
			}
			
			if (isset($objects[$id])) {
				if (is_array($objects[$id])) {
					require_once("Gene/Object/Model/".ucfirst($objects[$id]['type']).".php");
					$obj_class = "Gene_Object_Model_".ucfirst($objects[$id]['type']);
					
					$objects[$id] =& new $obj_class($objects[$id]);
				}
				
				$r =& $objects[$id];
			} else {
				$r = GENE_OBJECT_UNCACHED;
			}
		}
		
		return $r;
	}
	
	/**
	 * Returns a cached object
	 *
	 * @var mixed $id Object ID or alias
	 *
	 * @return mixed Cached Object or GENE_OBJECT_UNCACHED
	 */
	function &getCachedObject($id) {
		$i = null;
		$object =& Gene_Object::cacheObject($id, $i);
		return $object;
	}
}
 
?>